/***********************************************************************************
 @file   
 @author
 @attention
 ***********************************************************************************/
#include "slave_soft_iic.h"
/***********************************************************************************
@param
***********************************************************************************/


/***********************************************************************************
 * @brief  系统us延时
***********************************************************************************/
void delay_us(__IO uint32_t us)
{
    us*=3;
    while (us != 0)
    {
        us--;
    }
}


void IIC_Init(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);  //打开GPIO外设时钟门控
      
     ///< 端口方向配置->输出
    stcGpioCfg.enDir = GpioDirOut;
    stcGpioCfg.enPu  = GpioPuEnable;
    stcGpioCfg.enPd  = GpioPdDisable;
    stcGpioCfg.enDrv = GpioDrvH;
    
    Gpio_Init(IIC_SCL_PORT, IIC_SCL_PIN, &stcGpioCfg);
    Gpio_ClrIO(IIC_SCL_PORT, IIC_SCL_PIN); 
    
    Gpio_Init(IIC_SDA_PORT, IIC_SDA_PIN, &stcGpioCfg);
    Gpio_ClrIO(IIC_SDA_PORT, IIC_SDA_PIN);
    
    IIC_SCL(1);
    IIC_SDA(1);    
}



void SDA_OUT(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);  //打开GPIO外设时钟门控
      
     ///< 端口方向配置->输出
    stcGpioCfg.enDir = GpioDirOut;
    stcGpioCfg.enPu = GpioPuEnable;
    stcGpioCfg.enPd = GpioPdDisable;

    
    Gpio_Init(IIC_SCL_PORT, IIC_SCL_PIN, &stcGpioCfg);
    Gpio_ClrIO(IIC_SCL_PORT, IIC_SCL_PIN); 
    
    Gpio_Init(IIC_SDA_PORT, IIC_SDA_PIN, &stcGpioCfg);
    Gpio_ClrIO(IIC_SDA_PORT, IIC_SDA_PIN);
}

    
void SDA_IN(void)
{
    stc_gpio_cfg_t stcGpioCfg;   
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);  //打开GPIO外设时钟门控        
    ///< 端口方向配置->输入
    stcGpioCfg.enDir = GpioDirIn;
    stcGpioCfg.enDrv = GpioDrvL;
    stcGpioCfg.enPu = GpioPuEnable;
    stcGpioCfg.enPd = GpioPdDisable;
    stcGpioCfg.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    stcGpioCfg.enCtrlMode = GpioAHB;
    //---------------------------------------------按键输入上拉并配置下降沿中断
    Gpio_Init(IIC_SDA_PORT, IIC_SDA_PIN, &stcGpioCfg); 
}


void IIC_Start(void)
{
    SDA_OUT();     //sda线输出
    IIC_SDA(1);            
    IIC_SCL(1);
    delay_us(5);
    IIC_SDA(0);//START:when CLK is high,DATA change form high to low 
    delay_us(6);
    IIC_SCL(0);//钳住I2C总线，准备发送或接收数据 
}    


void IIC_Stop(void)
{
    SDA_OUT();//sda线输出
    IIC_SCL(0);
    IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
     IIC_SCL(1); 
    delay_us(6);
    IIC_SDA(1);//发送I2C总线结束信号
    delay_us(6);                                   
}

uint8_t IIC_Wait_Ack(void)
{
    uint8_t tempTime=0;
    SDA_IN();      //SDA设置为输入  
    IIC_SDA(1);
    delay_us(1);       
    IIC_SCL(1);
    delay_us(1);     
    while(READ_SDA)
    {
        tempTime++;
        if(tempTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_SCL(0);//时钟输出0        
    return 0;  
} 

void IIC_Ack(void)
{
    IIC_SCL(0);
    SDA_OUT();
    IIC_SDA(0);
    delay_us(2);
    IIC_SCL(1);
    delay_us(5);
    IIC_SCL(0);
}

void IIC_NAck(void)
{
    IIC_SCL(0);
    SDA_OUT();
    IIC_SDA(1);
    delay_us(2);
    IIC_SCL(1);
    delay_us(5);
    IIC_SCL(0);
}    
void IIC_Send_Byte(uint8_t txd)
{                        
    uint8_t t;   
    SDA_OUT();         
    IIC_SCL(0);//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        if((txd&0x80)>0) //0x80  1000 0000
            IIC_SDA(1);
        else
            IIC_SDA(0);
        txd<<=1;       
        delay_us(2);   //三个延时是必须的
        IIC_SCL(1);
        delay_us(2); 
        IIC_SCL(0);    
        delay_us(2);
    }     
} 


uint8_t IIC_Read_Byte(uint8_t ack)
{
    uint8_t i,receive=0;
    SDA_IN();//SDA设置为输入
  for(i=0;i<8;i++ )
    {
    IIC_SCL(0); 
        delay_us(2);
        IIC_SCL(1);
    receive<<=1;
   if(READ_SDA)receive++;   
        delay_us(1); 
    }                     
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}
